package com.cwg.dict.service.impl;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.edu.ynu.sei.dict.plugin.stardict.StarDictReader;
import cn.edu.ynu.sei.dict.service.core.IDictQueryService;

import com.cwg.dict.service.DictManager;
import com.cwg.dict.service.NetDictQueryService;

public class DictManagerImpl implements DictManager, NetDictQueryService {

	private int									dictCountHolder;
	private Map<String, String>					dicts		= new HashMap<String, String>();
	private final Map<String, StarDictReader>	dictsCache	= new HashMap<String, StarDictReader>();
	private FileHelper							fileHelper;
	private LoadHelper							loadHelper;
	private Logger								logger		= LoggerFactory.getLogger(DictManagerImpl.class);

	@Override
	public IDictQueryService[] allDictServices() {
		Collection<IDictQueryService> results = new ArrayList<IDictQueryService>();
		int loadedDictCount = 1;
		for (File each : fileHelper.allDictDirectories()) {
			addDictToCacheIfNecessary(each);
			String dicName = loadHelper.getDicName(each);
			StarDictReader dictService = dictsCache.get(dicName);
			results.add(dictService);
			if (isDictionaryCountChanged()) {
				int totalDictCount = fileHelper.allDictDirectories().length;
				System.out.printf("loading dictionaries [%3d/%-3d] from %s\n", loadedDictCount++, totalDictCount, each.getAbsolutePath());
			}
		}
		// hold the service size for comparing at isDictionaryCountChanged()
		dictCountHolder = results.size();
		return results.toArray(new IDictQueryService[results.size()]);
	}

	public FileHelper getFileHelper() {
		return fileHelper;
	}

	public LoadHelper getLoadHelper() {
		return loadHelper;
	}

	@Override
	public String[] getWordList(String word) {
		SortedSet<String> results = new TreeSet<String>();
		try {
			InputStream is = DictManagerImpl.class.getResourceAsStream("/wordlist.txt");
			List<String> readLines = IOUtils.readLines(is);
			/* 
			 * Using SortedSet to filter out the duplicated word and sort by alpha order
			 */
			for (String each : readLines) {
				if (StringUtils.isAlpha(each)) {
					if ("".equals(word)) {
						results.add(each);
					} else if (StringUtils.startsWithIgnoreCase(each, word)) {
						results.add(each);
					}
				}
			}

		} catch (IOException e) {
			e.printStackTrace();
			String msg = "can't load word list file at /wordlist.txt";
			System.err.println(msg);
			logger.error(msg, e);
		}

		return results.toArray(new String[results.size()]);
	}

	public Map<String, String> initDefaultNetDicts() {
		dicts.put("longman", "http://www.ldoceonline.com/search/?q=%s");
		//dicts.put("dreye", "http://www.dreye.com:8080/axis/ddict.jsp?w=%s&ver=big5");
		dicts.put("yahoo", "http://tw.dictionary.yahoo.com/search?ei=UTF-8&p=%s");
		dicts.put("encarta", "http://encarta.msn.com/dictionary_/%s.html");
		dicts.put("dictionary", "http://dictionary.reference.com/browse/%s");
		dicts.put("merriam-webster", "http://www.merriam-webster.com/dictionary/%s");
		dicts.put("answers", "http://www.answers.com/%s");
		dicts.put("wiktionary", "http://en.wiktionary.org/wiki/%s");

		return dicts;
	}

	public String makeQueryUrl(String dictName, String input) {
		return String.format(dicts.get(dictName), input);
	}

	public void setFileHelper(FileHelper fileHelper) {
		this.fileHelper = fileHelper;
	}

	public void setLoadHelper(LoadHelper loadHelper) {
		this.loadHelper = loadHelper;
	}

	private void addDictToCacheIfNecessary(File dir) {
		String dicName = loadHelper.getDicName(dir);
		if (dictsCache.get(dicName) == null) {
			StarDictReader entity = loadHelper.getDictQueryService(dir);
			dictsCache.put(dicName, entity);
		}
	}

	private boolean isDictionaryCountChanged() {
		return dictCountHolder != dictsCache.size();
	}

}
